/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package vnc;

import java.io.*;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.lcdui.*;

import javax.microedition.midlet.*;
import javax.microedition.lcdui.*;

/**
 *
 * @author Administrator
 */
public class VNC_Canves extends Canvas implements Runnable, CommandListener {

    Image Alertimage;
    private String error;
    private String send_text;
    public static StreamConnection sc;
    public static DataInputStream dis;
    public static DataOutputStream dos;
    private Image img;
    private Font font;
    private byte[] tmp,  msg;
    private int xp,  yp,  width,  height,  swidth,  sheight;
    private int bpp,  rmax,  gmax,  bmax,  mr,  mg,  mb,  nr,  ng,  nb,  dr,  dg,  db;
    private int rshift,  gshift,  bshift,  truecolor;
    private int bigend,  depth;
    private int pxsize,  dmode,  devdepth,  devcolors;
    private int[] palette;
    private boolean fixpalette = false;
    public static boolean running;
    private int menusize,  ms34;
    private int mousebuttons = 0,  lastx,  lasty;
    private int status = 0;
    private String desktop;
    private boolean scrolled;
    private Display disp;
    private TextBox tb;
    //-------------------- Control keys ----------------------------------------
    private List keyslist,  Functionlist;
    String currentMenu = null;
    private Command exit = new Command("Back", Command.EXIT, 1);
    private Command send = new Command("Send", Command.EXIT, 2);
    private Command submit = new Command("Submit", Command.SCREEN, 2);
    //---------------------------------------------------------------------------
    private Command tbok = new Command("Connect", Command.OK, 1),  tbnm = new Command("Exit", Command.CANCEL, 2),  inpt = new Command("Input", Command.OK, 1),  dcon = new Command("Disconnect", Command.BACK, 2);
    private Alert mModalAlert;
    private Command can = new Command("Cancel", Command.CANCEL, 1);
    private Command confir = new Command("Confirm", Command.OK, 1);
    //=================Input Form ============
    private Form Input;
    public TextField hostportfield;
    public TextField passField;
    public String gethost,  getpass;
    Spacer space;
    ChoiceGroup choiceGroup;
    Alert alert;
    //++++++++++++++++++++++++++++++++++++++++++++
    MIDlet mymidlet;

    public VNC_Canves(Interface mymidlet) {
        this.mymidlet = mymidlet;

        addCommand(inpt);
        addCommand(dcon);
        setCommandListener(this);
    }

    public void init() {
        width = getWidth();
        height = getHeight();

        ms34 = menusize * 3 / 4;
        xp = 0;
        yp = 0;
        img = Image.createImage(width, height);
        tmp = new byte[128];
        msg = new byte[24];
        font = Font.getFont(Font.FACE_SYSTEM, Font.STYLE_PLAIN, Font.SIZE_SMALL);
        error = null;
        running = true;
        scrolled = true;
        try {
            sc.close();
        } catch (Exception e) {
        }
        //------------ Start Create our forms for Program -----------------
        if (Functionlist == null) {
            Create_Functionlist();
        }
        if (keyslist == null) {

            Create_KeysList();
        }
        if (Input == null) {
            Create_InputForm();
        }
        if (alert == null) {
            Create_AlertForm();
        }
        if (tb == null) {
            Creat_textBox();
        }
    }

    //+++++++++++++++++++++++ Create the u ser Form in VNC +++++++++++++++++++++++++++
    //========= Create User Input Form to connect server
    public void Create_InputForm() {
        Input = new Form("VNC Input");
        hostportfield = new TextField("Host:port", "192.168.1.7:5900", 32, TextField.ANY);
        passField = new TextField("Password", "", 32, TextField.ANY);
        space = new Spacer(30, 20);
        choiceGroup = new ChoiceGroup("Save my password", Choice.EXCLUSIVE);
        choiceGroup.append("Yes ", null);
        choiceGroup.append("No", null);
        choiceGroup.setSelectedFlags(new boolean[]{false, false});
        choiceGroup.setFont(0, null);
        choiceGroup.setFont(1, null);

        Input.append(hostportfield);
        Input.append(passField);
        Input.append(space);
        Input.append(choiceGroup);

        Input.addCommand(tbok);
        Input.addCommand(tbnm);

        Input.setCommandListener(this);
    }
    //=========== Create ALert Form =====================

    public void Create_AlertForm() {
        alert = new Alert("VNC Alert", "You will be disconnected now", getAlertImage(), AlertType.CONFIRMATION);
        alert.addCommand(confir);
        alert.addCommand(can);
        alert.setCommandListener(this);
        alert.setTimeout(Alert.FOREVER);
        // write post-init user code here
        alert.setCommandListener(this);


    }
    //============== Create FOrm for Text Box =====================

    public void Creat_textBox() {
        tb = new TextBox("VNC Viewer Input", "", 120, TextField.ANY);
        tb.addCommand(exit);
        tb.addCommand(send);
        tb.setCommandListener(this);
    }
    //============= Create Keyboard Keys List ==================

    public void Create_KeysList() {
        keyslist = new List("Select keys", List.EXCLUSIVE);

        keyslist.append("Alt-F4", null);//0

        keyslist.append("Escape", null);//1

        keyslist.append("Ctrl-Alt-Del", null);//2

        keyslist.append("Ctrl-Shift-Esc", null);//3

        keyslist.append("Alt-F1", null);//4

        keyslist.append("Alt-F2", null);//5

        keyslist.append("Win-R", null);//6

        keyslist.append("Alt Down", null);//7

        keyslist.append("Alt Up", null);//8

        keyslist.append("Ctrl Down", null);//9

        keyslist.append("Ctrl Up", null);//10

        keyslist.append("Shift Down", null);//11

        keyslist.append("Shift Up", null);//12

        keyslist.append("Fun Keys", null);//13
        //=================== Remove Function Key ==========================// 
//        keyslist.append("F1", null);//13
//        keyslist.append("F2", null);//14
//        keyslist.append("F3", null);//15
//        keyslist.append("F4", null);//16
//        keyslist.append("F5", null);//17
//        keyslist.append("F6", null);//18
//        keyslist.append("F7", null);//19
//        keyslist.append("F8", null);//20
//        keyslist.append("F9", null);//21
//        keyslist.append("F10", null);//22
//        keyslist.append("F11", null);//23
//        keyslist.append("F12", null);//24

        keyslist.append("Enter Text", null);//14

        currentMenu = "list";
        keyslist.addCommand(exit);
        keyslist.addCommand(submit);
        keyslist.setCommandListener(this);

    }

    public void Create_Functionlist() {
        //keyslist.setCommandListener(null);
        Functionlist = new List("Function keys", List.EXCLUSIVE);
        
        Functionlist.append("Select", null); //---------------------> Item 0
        
        Functionlist.append(" F1 ", null); //---------------------> Item 1

        Functionlist.append(" F2 ", null); //---------------------> Item 2

        Functionlist.append(" F3 ", null); //---------------------> Item 3

        Functionlist.append(" F4 ", null); //---------------------> Item 4

        Functionlist.append(" F5 ", null); //---------------------> Item 5

        Functionlist.append(" F6 ", null); //---------------------> Item 6

        Functionlist.append(" F7 ", null); //---------------------> Item 7

        Functionlist.append(" F8 ", null); //---------------------> Item 8

        Functionlist.append(" F9 ", null); //---------------------> Item 9

        Functionlist.append(" F10 ", null); //---------------------> Item 10

        Functionlist.append(" F11 ", null); //---------------------> Item 11

        Functionlist.append(" F12 ", null); //---------------------> Item 12

        //currentMenu = "Functionlist";
        Functionlist.addCommand(exit);
        Functionlist.addCommand(submit);

        Functionlist.setCommandListener(this);

    }
    //+++++++++++++++++++++++ End of Creating Forms ++++++++++++++++++++++++++++++++++=

    public void setDisplay(Display d) {
        disp = d;
    }

    public void paint(Graphics g) {
        g.setColor(0xFFFFFF);
        g.fillRect(0, height, width, menusize);

        if (status == 1) {
            g.setColor(0);
            g.fillRect(width - ms34 + 2, height + 2, ms34 - 2, menusize - 2);
        } else {
            g.drawImage(img, 0, 0, g.LEFT | g.TOP);
            g.setColor(0);

            g.setFont(font);

        }
    }

    public int connect(String host, String pw) {
        int major = 0, minor = 0, t = 0;
        try {
            sc = (StreamConnection) Connector.open("socket://" + host);
            dis = sc.openDataInputStream();
            dos = sc.openDataOutputStream();
            dis.readFully(tmp, 0, 12);
            for (int i = 4; i < 7; i++) {
                major = major * 10 + (tmp[i] - 0x30);
                minor = minor * 10 + (tmp[i + 4] - 0x30);
            }
            System.err.println("Server " + major + "." + minor);
            dos.write(new String("RFB 003.003\n").getBytes());
            t = dis.readInt();
            if (t == 0) {
                return 1;
            } //connection failed

            if (t == 2) {
                System.err.println("VNC auth");
                dis.readFully(tmp, 0, 16);
                VNCEncrypt.vncMagic(tmp, pw);
                System.gc();
                dos.write(tmp, 0, 16);
                t = dis.readInt();
                if (t > 0) {
                    System.err.println("Auth failed: " + t);
                    return 2; //auth failed

                }
            }
            dos.write(1); //share connection

            swidth = dis.readUnsignedShort();
            sheight = dis.readUnsignedShort();
            bpp = dis.read();
            depth = dis.read();
            bigend = dis.read();
            truecolor = dis.read();
            rmax = dis.readUnsignedShort();
            gmax = dis.readUnsignedShort();
            bmax = dis.readUnsignedShort();
            rshift = dis.read();
            gshift = dis.read();
            bshift = dis.read();

            System.err.println(bpp + " bpp");
            System.err.println(depth + " depth");
            System.err.println(bigend + " bigendian");
            System.err.println(truecolor + " truecolor");
            System.err.println(rmax + " redmax");
            System.err.println(gmax + " greenmax");
            System.err.println(bmax + " bluemax");
            System.err.println(rshift + " redshift");
            System.err.println(gshift + " greenshift");
            System.err.println(bshift + " blueshift");

            t = 101; //for error handler


            System.err.println("Best guess");
            int d = 0, n = 1;
            for (int i = 1; i < 32; i++) {
                n = n * 2;
                if (n == disp.numColors()) {
                    d = i;
                    break;
                }
            }
            devdepth = d;
            devcolors = disp.numColors();
            if (d == 0) { //weird color count, we'll just bgr233

                bpp = 8;
                depth = 8;
                bigend = 1;
                truecolor = 1;
                rmax = 7;
                gmax = 7;
                bmax = 3;
                rshift = 0;
                gshift = 3;
                bshift = 6;

            } else {
                if (disp.isColor()) {
                    if (d > 18) { //more than 18 bits, use 24

                        bpp = 32;
                        depth = 24;
                        bigend = 1;
                        truecolor = 1;
                        rmax = 255;
                        gmax = 255;
                        bmax = 255;
                        rshift = 16;
                        gshift = 8;
                        bshift = 0;
                    } else if (d > 12) { //12-18, use 16 bit

                        bpp = 16;
                        depth = 16;
                        bigend = 1;
                        truecolor = 1;
                        rmax = 63;
                        gmax = 31;
                        bmax = 31;
                        rshift = 10;
                        gshift = 5;
                        bshift = 0;
                    } else if (d > 8) { //8-12, use 12bit map

                        bpp = 8;
                        depth = 12;
                        bigend = 1;
                        truecolor = 0;
                    } else { //else bgr233

                        bpp = 8;
                        depth = 8;
                        bigend = 1;
                        truecolor = 1;
                        rmax = 7;
                        gmax = 7;
                        bmax = 3;
                        rshift = 0;
                        gshift = 3;
                        bshift = 6;
                    }
                } else { //grayscale

                    if (d > 8) { //use 15bit

                        bpp = 16;
                        depth = 15;
                        bigend = 1;
                        truecolor = 1;
                        rmax = 31;
                        gmax = 31;
                        bmax = 31;
                        rshift = 10;
                        gshift = 5;
                        bshift = 0;
                    } else {
                        fixpalette = true;
                        bpp = 8;
                        depth = d;
                        bigend = 1;
                        truecolor = 0;
                    }
                }
            }


            System.err.println(".............");
            System.err.println(bpp + " bpp");
            System.err.println(depth + " depth");
            System.err.println(bigend + " bigendian");
            System.err.println(truecolor + " truecolor");
            System.err.println(rmax + " redmax");
            System.err.println(gmax + " greenmax");
            System.err.println(bmax + " bluemax");
            System.err.println(rshift + " redshift");
            System.err.println(gshift + " greenshift");
            System.err.println(bshift + " blueshift");

            for (int i = 0; i < 3; i++) {
                dis.read();
            }
            t = dis.readInt();
            dis.readFully(tmp, 0, t);
            desktop = new String(tmp, 0, t);


            synchronized (dos) {
                dos.write(0);
                for (int i = 0; i < 3; i++) {
                    dos.write(0);
                }
                dos.write(bpp);
                dos.write(depth);
                dos.write(bigend);
                dos.write(truecolor);
                dos.writeShort(rmax);
                dos.writeShort(gmax);
                dos.writeShort(bmax);
                dos.write(rshift);
                dos.write(gshift);
                dos.write(bshift);
                for (int i = 0; i < 3; i++) {
                    dos.write(0);
                }
            }


            synchronized (dos) {
                dos.write(2); //accepted encodings

                dos.write(0);
                dos.writeShort(2);
                dos.writeInt(4);//CoRRE

                dos.writeInt(0);//raw

            }

            t = calcColors();
            if (t == -1) {
                return 3;
            }

            new Thread(this).start();
            return 0;
        } catch (Exception e) {
            error = e.toString();
            if (t == 101) {
                error += ", tried another color mode?";
            }
            e.printStackTrace();
            return -1;
        }
    }

    private int getColor(int px) {
        return (((px >>> rshift) & rmax) << nr) | (((px >>> gshift) & gmax) << ng) | (((px >>> bshift) & bmax) << nb);
    }

    private int calcColors() {
        int r, g, b, t;
        pxsize = bpp >> 3; //assume no broken bytes

        palette = null;
        for (t = 0; t < 32; t++) {
            if (((1 << t) & rmax) == 0) {
                break;
            }
        }
        mr = t;
        for (t = 0; t < 32; t++) {
            if (((1 << t) & gmax) == 0) {
                break;
            }
        }
        mg = t;
        for (t = 0; t < 32; t++) {
            if (((1 << t) & bmax) == 0) {
                break;
            }
        }
        mb = t;

        nr = 24 - mr;
        ng = 16 - mg;
        nb = 8 - mb;
        dr = 0xFF / rmax;
        dg = 0xFF / gmax;
        db = 0xFF / bmax;

        if (pxsize > 4) {
            System.err.println("Too many colors: " + bpp + "b, " + pxsize);
            return -1;
        }
        if (pxsize == 1) {
            palette = new int[256];
            if (truecolor == 1) {
                for (int i = 0; i < 256; i++) {
                    r = (i >>> rshift) & rmax;
                    g = (i >>> gshift) & gmax;
                    b = (i >>> bshift) & bmax;
                    palette[i] = (r * dr << 16) | (g * dg << 8) | (b * db);
                }
            } else if (fixpalette && devcolors < 256) {
                t = 256 / devcolors;
                for (int i = 0; i < devcolors; i++) {
                    r = t * i;
                    palette[i] = (r << 16) | (r << 8) | r;
                }
//                fixPalette(0,devcolors); //Unsupported by servers
            }
            dmode = 1; //palette

        } else {
            System.err.println("Crazy color scheme");
            dmode = 0; //manual

        }
        System.gc();
        System.err.println("Pixsize: " + pxsize + ", Drawmode: " + dmode);
        return 0;
    }

    public void fixPalette(int off, int len) {
        System.err.println("Fixpalette: " + off + ", " + len);
        int r, g, b;
        synchronized (dos) {
            try {
                dos.write(1);
                dos.write(0);
                dos.writeShort(off);
                dos.writeShort(len);
                for (int i = 0; i < len; i++) {
                    r = (palette[off + i] >>> 8) & 0xFF00;
                    g = (palette[off + i]) & 0xFF00;
                    b = (palette[off + i] << 8) & 0xFF00;
                    dos.writeShort(r);
                    dos.writeShort(g);
                    dos.writeShort(b);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void update() throws IOException {
        synchronized (dos) {
            dos.write(3);
            dos.write(scrolled ? 0 : 1);
            dos.writeShort(xp);
            dos.writeShort(yp);
            dos.writeShort(width);
            dos.writeShort(height);
            scrolled = false;
        }
    }

    public void scroll(int dir) {
        synchronized (dos) {
            scrolled = true;
            switch (dir) {
                case 0: //up

                    yp -= height * 4 / 5;
                    yp = Math.max(0, yp);
                    break;
                case 1: //down

                    yp += height * 4 / 5;
                    yp = Math.min(yp, sheight - height);
                    break;
                case 2: //left

                    xp -= width * 4 / 5;
                    xp = Math.max(0, xp);
                    break;
                case 3: //right

                    xp += width * 4 / 5;
                    xp = Math.min(xp, swidth - width);
                    break;
            }
        }
        try {
            update();
        } catch (Exception e) {
            running = false;
            error = e.toString();
            e.printStackTrace();
            notifyAll();
        }
    }

    protected void keyPressed(int keycode) {
        int n = getGameAction(keycode);
        synchronized (dos) {
            //press 5 to send ENTER
            if (keycode == KEY_NUM5) {
                try {

                    sendChar(0xFF8D);

                } catch (Exception exception) {
                }

            }
            //press 4 to send LEFT
            if (keycode == KEY_NUM4) {
                try {

                    sendChar(0xFF51);

                } catch (Exception exception) {
                }
            }
            //press 2 to send UP
            if (keycode == KEY_NUM2) {
                try {

                    sendChar(0xFF52);

                } catch (Exception exception) {
                }
            }
            //press 6 to send RIGHT
            if (keycode == KEY_NUM6) {
                try {

                    sendChar(0xFF53);

                } catch (Exception exception) {
                }
            }
            //press 8 to send DOWN 
            if (keycode == KEY_NUM8) {
                try {

                    sendChar(0xFF54);

                } catch (Exception exception) {
                }
            }
            //press 1 to send TAB 
            if (keycode == KEY_NUM1) {
                try {

                    sendChar(0xFF09);

                } catch (Exception exception) {
                }
            }
            //press 0 to send Space
            if (keycode == KEY_NUM0) {
                try {

                    sendChar(0x020);

                } catch (Exception exception) {
                }
            }
            //press 3 to send BACK_SPACE

            if (keycode == KEY_NUM3) {
                try {

                    sendChar(0xFF08);

                } catch (Exception exception) {
                }
            }
            //press 9 to send MENU(Hyper)
            if (keycode == KEY_NUM9) {
                try {

                    sendChar(0xFFED);

                } catch (Exception exception) {
                }
            }

            if (keycode == KEY_NUM7) {
                try {

                    sendChar(0xFFEB);
                    

                } catch (Exception exception) {
                }
            }
            //press # to switch between windows
            if (keycode == KEY_POUND) {
                try {
                    setupChars();
                    sendKeyPressed(0xFFE9);
                    sendChar(0xff09);
                    sendKeyReleased(0xFFE9);

                } catch (Exception exception) {
                }
            }
            //------end of keys----------
            try {

                update();
            } catch (Exception e) {
            }

            switch (n) {
                case UP:
                    scroll(0);
                    System.out.println("up");
                    break;
                case DOWN:
                    scroll(1);
                    break;
                case LEFT:
                    scroll(2);
                    break;
                case RIGHT:
                    scroll(3);
                    break;
                case FIRE:

                    try {
                        update();
                        System.out.println("fire");
                    } catch (Exception e) {
                        running = false;
                        error = e.toString();
                        e.printStackTrace();
                        notifyAll();
                    }
                    break;

            }
        }
    }

    public String getError() {
        return error;
    }

    public boolean hasError() {
        return error != null;
    }

    public void run() {
        int packtype, rectnum, xpos, ypos, w, h, ow, oh, enc;
        int px, fpx;
        int t, u, v;
        Graphics g;
        g = img.getGraphics();
        g.setColor(0x5500FF);
        g.fillRect(10, 10, 20, 20);
        g.setFont(font);
        g.setColor(0x000000);
        g.drawString("Connected to", 0, 34, g.TOP | g.LEFT);
        g.drawString(desktop, 0, 68, g.TOP | g.LEFT);
        g.drawString("Press fire to connect.", 0, 102, g.TOP | g.LEFT);
        g.drawString(" --- VNC Viewer ---", 80, 142, g.TOP | g.LEFT);
        repaint();
        serviceRepaints();
        try {
            while (running) {
                packtype = dis.read();
                if (packtype == 0) { //FramebufferUpdate

                    status = 1;
                    repaint();
                    dis.read();  //padding

                    rectnum = dis.readUnsignedShort();
                    for (int k = 0; k < rectnum; k++) {
                        xpos = dis.readUnsignedShort() - xp;
                        ypos = dis.readUnsignedShort() - yp;
                        w = dis.readUnsignedShort();
                        h = dis.readUnsignedShort();
                        enc = dis.readInt();
//                    System.err.println(xpos+","+ypos+" "+w+"x"+h+": "+enc+" ("+dmode+")");
                        if (enc == 0) {
//                      System.err.println("Raw: "+xpos+","+ypos+": "+w+"x"+h);
                            ow = w + xpos;
                            oh = h + ypos;
                            switch (dmode) {
                                case 0: //manual

                                    for (int i = ypos; i < oh; i++) {
                                        for (int j = xpos; j < ow; j++) {
                                            px = 0;
                                            dis.readFully(tmp, 0, pxsize);
                                            for (int l = 0; l < pxsize; l++) {
                                                px = (px << 8) | (tmp[l] & 0xFF);
                                            }
                                            px = getColor(px);
                                            g.setColor(px);
                                            g.drawRect(j, i, 1, 1);
                                        }
                                    }
                                    break;
                                case 1: //use palette

                                    fpx = h * w;
                                    px = 0;
                                    u = xpos;
                                    v = ypos;
                                    while (px < fpx) {
                                        t = dis.read(tmp, 0, Math.min(tmp.length, fpx - px));
                                        for (int i = 0; i < t; i++) {
                                            g.setColor(palette[tmp[i] & 0xFF]);
                                            g.drawRect(u, v, 1, 1);
                                            px++;
                                            u++;
                                            if (u == ow) {
                                                u = xpos;
                                                v++;
                                            }
                                        }
                                    }
                                    break;
                            } //switch

                        } else if (enc == 4) {
                            t = dis.readInt();
//                  System.err.println(t+" tiles, "+w+"x"+h+" "+xpos+","+ypos);
                            px = 0;
                            switch (dmode) {
                                case 0:
                                    for (int i = 0; i < pxsize; i++) {
                                        px = (px << 8) | dis.read();
                                    }
                                    px = getColor(px);
                                    break;
                                case 1:
                                    px = palette[dis.read()];
                                    break;
                            }
                            g.setColor(px);
                            g.fillRect(xpos, ypos, w, h);
                            switch (dmode) {
                                case 0:
                                    for (int j = 0; j < t; j++) {
                                        px = 0;
                                        dis.readFully(tmp, 0, pxsize);
                                        for (int i = 0; i < pxsize; i++) {
                                            px = (px << 8) | (tmp[i] & 0xFF);
                                        }
                                        g.setColor(getColor(px));
                                        u = dis.read() + xpos;
                                        v = dis.read() + ypos;
                                        g.fillRect(u, v, dis.read(), dis.read());
                                    }
                                    break;
                                case 1:
                                    for (int j = 0; j < t; j++) {
                                        dis.readFully(tmp, 0, 5);
                                        g.setColor(palette[tmp[0] & 0xFF]);
                                        g.fillRect((tmp[1] & 0xFF) + xpos, (tmp[2] & 0xFF) + ypos, tmp[3] & 0xFF, tmp[4] & 0xFF);
//                                    System.err.println(((tmp[1]&0xFF)+xpos)+","+((tmp[2]&0xFF)+ypos)+": "+(tmp[3]&0xFF)+"x"+(tmp[4]&0xFF));
                                    }
                                    break;
                            }
                        } //enc
                        else {
                            System.err.println("Unknown encoding: " + enc);
                        }
                    } //rectnum

                    status = 0;
                    repaint();
                    serviceRepaints();
                } else if (packtype == 1) { //setcolourmapentries

                    dis.read();
                    t = dis.readUnsignedShort();
                    u = dis.readUnsignedShort();
//                System.err.println("SetColourMapEntries: "+t+","+u);
                    v = u + t;
                    for (int i = t; i < v; i++) {
                        u = (dis.readUnsignedShort() / 257);  //more accurate but slow

                        u = (dis.readUnsignedShort() / 257) | (u << 8);
                        u = (dis.readUnsignedShort() / 257) | (u << 8);
                        palette[i] = u;
                    }
                } else if (packtype == 2) {
                    System.err.println("Bell!");
                //beep? visual alert?
                } else if (packtype == 3) {
                    System.err.println("Server cut text.");

                    for (int i = 0; i < 3; i++) {
                        dis.read();
                    }
                    t = dis.readInt();
                    dis.read(tmp, 0, t);
                //keep?
                } else if (packtype == -1 && running) {
                    error = "End of stream.";
                    running = false;
                } else {
                    System.out.println("Unknown packet" + packtype);
                }
            } //running loop

        } catch (Exception e) {
            running = false;
            error = e.toString() + " in run()";
            e.printStackTrace();
        } finally {
            notifyAll();
        }
    }

    public void sendString(String s) throws IOException {
        synchronized (dos) {
            char ch;
            int key = 0xff;
            setupChars();

            for (int i = 0; i < s.length(); i++) {
                ch = s.charAt(i);
                switch (ch) {
                    case ' ':
                        key = 0x020;
                        break;
                    case '!':
                        key = 0x021;
                        break;
                    case '@':
                        key = 0x022;
                        break;
                    case '#':
                        key = 0x023;
                        break;
                    case '$':
                        key = 0x024;
                        break;
                    case '%':
                        key = 0x025;
                        break;
                    case '^':
                        key = 0x026;
                        break;
                    case '\'':
                        key = 0x027;
                        break;
                    case '{':
                        key = 0x028;
                        break;
                    case '}':
                        key = 0x029;
                        break;
                    case '*':
                        key = 0x02a;
                        break;
                    case '+':
                        key = 0x02b;
                        break;
                    case ',':
                        key = 0x02c;
                        break;
                    case '-':
                        key = 0x02d;
                        break;
                    case '.':
                        key = 0x02e;
                        break;
                    case '/':
                        key = 0x02f;
                        break;
                    case '0':
                        key = 0x030;
                        break;
                    case '1':
                        key = 0x031;
                        break;
                    case '2':
                        key = 0x032;
                        break;
                    case '3':
                        key = 0x033;
                        break;
                    case '4':
                        key = 0x034;
                        break;
                    case '5':
                        key = 0x035;
                        break;
                    case '6':
                        key = 0x036;
                        break;
                    case '7':
                        key = 0x037;
                        break;
                    case '8':
                        key = 0x038;
                        break;
                    case '9':
                        key = 0x039;
                        break;
                    case ':':
                        key = 0x03a;
                        break;
                    case ';':
                        key = 0x03b;
                        break;
                    case '<':
                        key = 0x03c;
                        break;
                    case '=':
                        key = 0x03d;
                        break;
                    case '>':
                        key = 0x03e;
                        break;
                    case '?':
                        key = 0x03f;
                        break;
                    case 'A':
                        key = 0x041;
                        break;
                    case 'B':
                        key = 0x042;
                        break;
                    case 'C':
                        key = 0x043;
                        break;
                    case 'D':
                        key = 0x044;
                        break;
                    case 'E':
                        key = 0x045;
                        break;
                    case 'F':
                        key = 0x046;
                        break;
                    case 'G':
                        key = 0x047;
                        break;
                    case 'H':
                        key = 0x048;
                        break;
                    case 'I':
                        key = 0x049;
                        break;
                    case 'J':
                        key = 0x04a;
                        break;
                    case 'K':
                        key = 0x04b;
                        break;
                    case 'L':
                        key = 0x04c;
                        break;
                    case 'M':
                        key = 0x04d;
                        break;
                    case 'N':
                        key = 0x04e;
                        break;
                    case 'O':
                        key = 0x04f;
                        break;
                    case 'P':
                        key = 0x050;
                        break;
                    case 'Q':
                        key = 0x051;
                        break;
                    case 'R':
                        key = 0x052;
                        break;
                    case 'S':
                        key = 0x053;
                        break;
                    case 'T':
                        key = 0x054;
                        break;
                    case 'U':
                        key = 0x055;
                        break;
                    case 'V':
                        key = 0x056;
                        break;
                    case 'W':
                        key = 0x057;
                        break;
                    case 'X':
                        key = 0x058;
                        break;
                    case 'Y':
                        key = 0x059;
                        break;
                    case 'Z':
                        key = 0x05a;
                        break;
                    case '(':
                        key = 0x05b;
                        break;

                    case ')':
                        key = 0x05d;
                        break;
                    case '_':
                        key = 0x05f;
                        break;

                    case 'a':
                        key = 0x061;
                        break;
                    case 'b':
                        key = 0x062;
                        break;
                    case 'c':
                        key = 0x063;
                        break;
                    case 'd':
                        key = 0x064;
                        break;
                    case 'e':
                        key = 0x065;
                        break;
                    case 'f':
                        key = 0x066;
                        break;
                    case 'g':
                        key = 0x067;
                        break;
                    case 'h':
                        key = 0x068;
                        break;
                    case 'i':
                        key = 0x069;
                        break;
                    case 'j':
                        key = 0x06a;
                        break;
                    case 'k':
                        key = 0x06b;
                        break;
                    case 'l':
                        key = 0x06c;
                        break;
                    case 'm':
                        key = 0x06d;
                        break;
                    case 'n':
                        key = 0x06e;
                        break;
                    case 'o':
                        key = 0x06f;
                        break;
                    case 'p':
                        key = 0x070;
                        break;
                    case 'q':
                        key = 0x071;
                        break;
                    case 'r':
                        key = 0x072;
                        break;
                    case 's':
                        key = 0x073;
                        break;
                    case 't':
                        key = 0x074;
                        break;
                    case 'u':
                        key = 0x075;
                        break;
                    case 'v':
                        key = 0x076;
                        break;
                    case 'w':
                        key = 0x077;
                        break;
                    case 'x':
                        key = 0x078;
                        break;
                    case 'y':
                        key = 0x079;
                        break;
                    case 'z':
                        key = 0x07a;
                        break;
                    case '|':
                        key = 0x07c;
                        break;
                    default:
                        return;
                }
                sendChar(key);
            }
        }
    }

    private void setupChars() {
        for (int i = 0; i < 16; i++) {
            msg[i] = 0;
        }
        msg[0] = msg[8] = 4;
        msg[1] = 1;
        msg[9] = 0;
    }

    /** Send a char. Do not call, use sendString instead. */
    private void sendChar(int c) throws IOException {
        setupChars();
        msg[6] = msg[14] = (byte) ((c >>> 8) & 0xFF);
        msg[7] = msg[15] = (byte) (c & 0xFF);

        //---------------------------------------------------------------------
        try {
            dos.write(msg, 0, 16);
            System.err.println("Cow!");

        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // sending pressed keys
    private void sendKeyPressed(int c) throws IOException {
        setupChars();
        msg[6] = msg[14] = (byte) ((c >>> 8) & 0xFF);
        msg[7] = msg[15] = (byte) (c & 0xFF);
        msg[9] = 1;
        try {
            dos.write(msg, 0, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    // sending released keys

    private void sendKeyReleased(int c) throws IOException {
        setupChars();
        msg[6] = msg[14] = (byte) ((c >>> 8) & 0xFF);
        msg[7] = msg[15] = (byte) (c & 0xFF);
        msg[1] = 0;
        try {
            dos.write(msg, 0, 8);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void commandAction(Command c, Displayable d) {
        System.gc();
        String label = c.getLabel();

        if (label.equals("Send")) {
            try {
                send_text = tb.getString();
                sendString(send_text);
            } catch (IOException ex) {
                ex.printStackTrace();
                System.out.println("Cant send that");
            }
        }
        if (label.equals("Back")) {

            if (currentMenu.equals("list") || currentMenu.equals("input")) {

                disp.setCurrent(this);

            }
        } else if (label.equals("Cancel")) {

            System.out.println("Cancel Disconnect Action");
            disp.setCurrent(this);

        } else if (label.equals("Exit")) {

            mymidlet.notifyPaused();
            mymidlet.notifyDestroyed();
        //-------------- Bneed to destroy app ---------
        } else if (label.equals("Confirm")) {
            System.out.println("Confirm disconnect");
            running = false;

            try {
                dos.write(0xFF); //let's try to get evicted. FIXME

                sc.close();
            } catch (Exception e) {
            }

            displayInputAgain();
            System.out.println("It should be changed now");

        } //========== When i click sbmit i should select what action yo do =====
        else if (label.equals("Submit")) {
            //------------ Action for each item in list-------------------------------
            System.out.println("---------Enter in List to choose action----------");

            //----------------Declire our lists ------------------
            int Keylist_index = keyslist.getSelectedIndex();
            synchronized (dos) {
                if (Keylist_index == 0) {//Alt-F4

                    try {
                        setupChars();
                        sendKeyPressed(0xFFE9);
                        sendChar(0xFFC1);
                        sendKeyReleased(0xFFE9);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }

                if (Keylist_index == 1) {
                    try {
                        sendChar(0xFF1B);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }



                if (Keylist_index == 2) {
                    try {
                        setupChars();
                        sendKeyPressed(0xFFE3);
                        sendKeyPressed(0xFFE9);
                        sendChar(0xFFFF);
                        sendKeyReleased(0xFFE9);
                        sendKeyReleased(0xFFE3);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 3) {
                    try {
                        setupChars();
                        sendKeyPressed(0xFFE3);
                        sendKeyPressed(0xffe9);
                        sendChar(0xff1b);
                        sendKeyReleased(0xffe9);
                        sendKeyReleased(0xffe3);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 4) {
                    try {
                        setupChars();
                        sendKeyPressed(0xffe9);
                        sendChar(0xffbe);
                        sendKeyReleased(0xffe9);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 5) {
                    try {
                        setupChars();
                        sendKeyPressed(0xffe9);
                        sendChar(0xffbf);
                        sendKeyReleased(0xffe9);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 6) {
                    try {
                        setupChars();
                        sendKeyPressed(0xFFEB);
                        sendChar(0x072);
                        sendKeyReleased(0xFFEB);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 7) {
                    try {
                        setupChars();
                        sendKeyPressed(0xFFE9);
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 8) {
                    try {
                        setupChars();
                        sendKeyReleased(0xFFE9);

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 9) {
                    try {
                        setupChars();
                        sendKeyPressed(0xFFE3);

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 10) {
                    try {
                        setupChars();
                        sendKeyReleased(0xFFE3);

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 11) {
                    try {
                        setupChars();

                        sendKeyPressed(0xFFE1);

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 12) {
                    try {
                        setupChars();
                        sendKeyReleased(0xFFE1);

                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                }
                if (Keylist_index == 13) {
                    System.gc();
                    disp.setCurrent(Functionlist);
                    System.out.println("The function list should appera");
                    synchronized (dos) {
                    int Functionlist_index = Functionlist.getSelectedIndex();
                    //----------------- Start of Function Keys ------------------
                    if (Functionlist_index == 1) {
                        try {
                            this.sendChar(0xffbe);
                            System.out.println("Send F1");
                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 2) {
                        try {
                            System.out.println("Send F2");
                            this.sendChar(0xffbf);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 3) {
                        try {
                            this.sendChar(0xffc0);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 4) {
                        try {
                            this.sendChar(0xffc1);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 5) {
                        try {
                            this.sendChar(0xffc2);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 6) {
                        try {
                            this.sendChar(0xffc3);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 7) {
                        try {
                            this.sendChar(0xffc4);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 8) {
                        try {
                            this.sendChar(0xffc5);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 9) {
                        try {
                            this.sendChar(0xffc6);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 10) {
                        try {
                            this.sendChar(0xffc7);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 11) {
                        try {
                            this.sendChar(0xffc8);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }
                    if (Functionlist_index == 12) {
                        try {
                            System.out.println("Send F12");
                            this.sendChar(0xffc9);

                        } catch (IOException ex) {
                            ex.printStackTrace();
                        }
                    }

                 }
                }


                //================ The txtbox ---------------------
                if (Keylist_index == 14) {
                    Display_textInput();
                    System.out.println("****************After Display The Text Box------------------");
                }
            }
        //=== Return to Remote desktop  ====
        //  disp.setCurrent(this);
        }


        if (c == tbok) {
            //======== Connect to server Again ============
            gethost = hostportfield.getString();
            getpass = passField.getString();
            AlertType.CONFIRMATION.playSound(disp);

            new Thread() {

                public void run() {

                    Reconnect(gethost, getpass);
                }
            }.start();

        } else if (d == this) {


            if (c == inpt) {
                //======== GO to display keys list Actions ==========
                displayKeys();

            } else if (c == dcon) {
                //===== Go to Alert Before Disconnect Action ======
                GotoAlert();

            }

        }
    }

    //======== Display Key list =============
    public void displayKeys() {
        // tb.setString("");
        disp.setCurrent(keyslist);
    }

    //========= Change to function list ===========
    public void displayFunKeys() {
        disp.setCurrent(Functionlist);
    }
    //=========== Display text Input ============

    public void Display_textInput() {
        disp.setCurrent(tb);
    }
    //--------- Switch Dispaly to Input Form ------------------------------

    public void displayInputAgain() {
        disp.setCurrent(Input);
    }
//-------- Connect to server with secound time -------------------------

    public void Reconnect(String host, String pa) {
        init();
        disp.setCurrent(this);
        int t = connect(host, pa);

        System.out.println("result of conn====" + t);
        if (t == 0) {
            synchronized (dos) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
                if (hasError()) {
                    displayError("Terminated", "Process ended: " + getError());
                } else {
                    disp.setCurrent(null);
                }
            }
            System.gc();
        }

        if (t == 1) {
            displayError("Connection failed",
                    "Failure during handshake");
        }
        if (t == 2) {
            displayError("Authentication failed", "Wrong password?");
            System.out.println("It's awrong password ---->");
        }
        if (t == 3) {
            displayError("Bad color mode", "Too many bytes per color");
        }
        if (t == -1) {
            displayError("Exception",
                    "Exception occurred during connect(): " + getError());
        }
//        else {
//            displayError("Unknown error code", "Error code: " + t);
//        }
    }
//-------------------- Switch Display to Alert option ------------------------

    public void GotoAlert() {
        disp.setCurrent(alert);
    }
//---------------- To get the Alert image -----------------------------------

    public Image getAlertImage() {
        if (Alertimage == null) {
            // write pre-init user code here
            try {
                Alertimage = Image.createImage("/Image/AlertImage.png");
            } catch (java.io.IOException e) {
                e.printStackTrace();
            }
        // write post-init user code here
        }
        return Alertimage;
    }

    //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    public void displayError(String title, String text) {
        System.out.println("I will display error now");
        Alert al = new Alert(title, text, getAlertImage(), AlertType.ERROR);
        al.addCommand(tbnm);
        al.setTimeout(al.FOREVER);
        al.setCommandListener(this);


        //---------Change display to error message 
        disp.setCurrent(al);
    }
}
